%% PluVelOpera - Operation of the time series classification system
%
% This script carries out these steps:
% 1) Access via FTP to a remote database where the data provided by 
%    pluviometer and total station are placed at scheduled times;
% 2) Access (if possible and required) to a remote database or to a web 
%    site with weather forecasts; 
% 3) Processing of monitoring data to provide rainfall and velocity time 
%    series compatible with the trained CNN or CNNs
% 4) Computation of the forecasts and saving of the results as a row
%                           [tc level],
%    where tc is the computation time and level is the foreseen level, 
%    appended to a specific file, and check of the time series limits;
% 5) Emission of an email and/or another signal for the decision maker;
% 6) MATLAB exit as the computations and data saving are completed.   

% G. Teza, 2020 

t = now;
% t = datenum(2020,1,20);     % <- for test purposes 
tv = datevec(t);
tc = datenum([tv(1:4) 0 0]);
tcs = datestr(tc);

fprintf('\nCalculation starts at %s (reference time: %s)\n',...
    datestr(t),tcs);  

disp('CNN load in progress...');
[~,~,RawFOP] = xlsread('OperaPreferences.xlsx');

% Load of ParamWN file:
ParamWNfile = readFOP(RawFOP,'ParamWNfile');
ParamWNs = load(ParamWNfile);
ParamWN = ParamWNs.ParamWN;

%Output data management:
FoldOperaRV = readFOP(RawFOP,'FoldOperaRV');
FoldOperaR  = readFOP(RawFOP,'FoldOperaR');
FileSGRV = readFOP(RawFOP,'FileSGRV');
FileSGR  = readFOP(RawFOP,'FileSGR');
OutputFileRV = readFOP(RawFOP,'OutputFileRV');
OutputFileR  = readFOP(RawFOP,'OutputFileR');

% Load of trained CNN with rainfall and velocity:
NetFileRV = readFOP(RawFOP,'NetFileRV');
nets = load(NetFileRV);
netRV = nets.net;

% Load of trained CNN with rainfall only:
NetFileR = readFOP(RawFOP,'NetFileR');
nets = load(NetFileR);
netR = nets.net;

disp('... done');
%% FTP to remote server and data download

disp('FTP to remote server in progress...');

dirTRfiles = readFOP(RawFOP,'dirTRfiles');
ftpSite = readFOP(RawFOP,'ftpSite');
ftpUser = readFOP(RawFOP,'ftpUser');
ftpPwd  = readFOP(RawFOP,'ftpPwd');
ftpobj = ftp(ftpSite,ftpUser,ftpPwd);
ftpSystem = readFOP(RawFOP,'ftpSystem');
if isempty(ftpSystem) || strcmpi(ftpSystem,'unix')  
    DataFolder = ['/' dirTRfiles '/'];      % UNIX 
else
    DataFolder = ['\' dirTRfiles '\'];      % WINDOWS
end

% download rainfall file (on local folder DataFolder) 
PluFilena = [DataFolder readFOP(RawFOP,'PluFilena')];
mget(ftpobj,PluFilena);

% download position file (on local folder DataFolder) 
PosFilena = [DataFolder readFOP(RawFOP,'PosFilena')];
mget(ftpobj,PosFilena);

disp('...done');

%% Download of wheater forecast data (if applicable) 

disp('Data download and pre-processing');

Na = ParamWN.Na;
Nb = ParamWN.Nb;
if Nb > 0
    WeatherFilena = [DataFolder readFOP(RawFOP,'WeatherFilena')];
    try 
        mget(ftpobj,WeatherFilena);
        Iforok = 1;
    catch
        Iforok = 0;
    end
end


%% Data processing aimed at providing the rainfall and velocity time series

% Rainfall data:
MR = extraPluvio(PluFilena,[],tc-Na,tc);

if Nb > 0
    if Iforok       % in this case, the rainfall forecast file was downloaded
        RF = extraPluvio(WheatherFilena,[],tc,tc+Nb);
    else            % in this case, no rainfall forecast data are available
        tRF = (tc:1/24:tc+Nb)';             % time column vector
        [~,I2d] = min(abs(MR(:,1)-tc+2));   % to allow the mean on the last two days 
        RRF = mean(MR(I2d:end,1))*ones(size(tRF));
        RF = [tRF RRF];
    end
    RF(1,:) = [];   % to remove the line with RF, which is already in MR
    MR = [MR; RF];
end

% Cumulative rainfall data:
M1 = cumPluvio(MR,1,1,tc-Na,tc);

% Position data:
try 
    MP = extraRTS2array(PosFilena);
catch
    MP = []; 
end

if ~isempty(MR)
    % Velocity array with 1-h time step (24 cpd) and mean on 1 d (24 h):  
    MVA = velArray(MP,1,24,[5 6 7]);
    % Velocity time series
    MV = selectMeanVelocity(MVA,[4 5 6 7],tc-Na,tc);
    I = isnan(MV(:,2));
    Itc = find(abs(MV(:,1)-tc) < 10^3*eps);
    if I(Itc) == 1
        ICalc = 0;
    else
        ICalc = 1;  % Forecasting based on rainfall and velocity enabled
    end
else
    ICalc = 0;
end

disp('... done');

%% Forecast evaluation and data save

disp('Forecast evaluation in progress...');

if ICalc
    if Nb == 0
        PluVel = [M1 MV(:,2)];
    else
        nrp = size(M1,1);
        nrv = size(MV,1);
        Vel = [MV(:,2); zeros(nrp-nrv,2)];
        PluVel = [M1 MV(:,2)];
    end
end
Plu = M1;

% Computation of the output level:
if ICalc
    try
        LRV = OutLevel(PluVel,tc,net,ParamWN,FoldOperaRV,FileOutRV);
        LLRV = {datestr(tc) LRV};
        IRVok = 1;
    catch
        LLRV = {datestr(tc) '-'};
        IRVok = 0; 
    end
else
    LLRV = {datestr(tc) '-'};
    IRVok = 0;
end
MRVL = load(OutputFileRV);
MRVL = [MRVL; LLRV];
save(OutputFileRV,'MRVL');

try
    LR  = OutLevel(PluVel,tc,netR,ParamWN,FoldOperaRV,FileOutR);
    LLR = {datestr(tc) LR};
    IRok = 1;
catch
    LLR = {datestr(tc) '-'};
    IRok = 0;
end
MRL = load(OutputFileR);
MRL = [MRL; LLR];
save(OutputFileR,'MRL');

% test

disp('... done');

%% Email setpref

disp('Send email in progress...');

setpref('Internet','SMTP_Server',readFOP(RawFOP,'SMTP_Server'));
setpref('Internet','E_mail',readFOP(RawFOP,'emailAddress'));
setpref('Internet','SMTP_Username',readFOP(RawFOP,'SMTP_Username'));
setpref('Internet','SMTP_Password',readFOP(RawFOP,'SMTP_Password'));
props = java.lang.System.getProperties;
props.setProperty('mail.smtp.auth','true');
props.setProperty('mail.smtp.socketFactory.class','javax.net.ssl.SSLSocketFactory');
props.setProperty('mail.smtp.socketFactory.port','465');

emailSubject = readFOP(RawFOP,'emailSubject');
emailReceivers = readFOP(RawFOP,'emailReceivers');

if IRVok    % forecast based on rainfall and velocity
    [TR,TV] = TimeSeriesLimCheck(PluVel,ParamWN);
    sWarn = 'BUT THE FORECAST IS NOT COHERENT WITH THE RAINFALL/VELOCITY DISTRIBUTIONS';
    switch LRV
        case 'L1'
            if ~TR || ~TV 
                emailText = sprintf('Time %s - LOW VELOCITY',tcs);
            else
                emailText = sprintf('Time %s - WARNING - LOW VELOCITY %s',tcs,sWarn);
            end
        case 'L2'
            if ~TR || ~TV
                emailText = sprintf(...
                    'Time %s - PRE-ALERT, TRANSITION LOW/MEDIUM VELOCITY',tcs);
            else
                emailText = sprintf(...
                    'Time %s -  WARNING - PRE-ALERT %s',tcs,sWarn);
            end
        case 'L3'
            if ~TR || ~TV
                emailText = sprintf(...
                    'Time %s - ALWAYS PRE-ALERT, MEDIUM VELOCITY',tcs);
            else
                emailText = sprintf(...
                    'Time %s -  WARNING - ALWAYS PRE-ALERT %s',tcs,sWarn);
            end
        case 'L4'
            emailText = sprintf(...
                'Time %s - ALARM, TRANSITION TO HIGH VELOCITY',tcs);
        case 'L5'
            emailText = sprintf('Time %s - ALWAYS ALARM, HIGH VELOCITY',tcs);
        case 'L6'
            emailText = sprintf(...
                'Time %s - TOWARDS ALARM RETURN, TRANSTION FROM HIGH TO MEDIUM VELOCITY',tcs);
        case 'L7'
            emailText = sprintf(...
                'Time %s - TOWARDS PRE-ALERT RETURN, TRANSTION FROM MEDIUM TO LOW VELOCITY',tcs);
    end
elseif IRok         % forecast based on rainfall only
    [TR,~] = TimeSeriesLimCheck(PluVel(:,1:2),ParamWN);
    sWarn = 'BUT THE FORECAST IS NOT COHERENT WITH THE RAINFALL DISTRIBUTION';
    switch LR
        case 'L1'
            if ~TR
                emailText = sprintf(...
                    'Time %s - LOW VELOCITY (FROM RAINFALL ONLY)',tcs);
            else
                emailText = sprintf(...
                    'Time %s - WARNING - LOW VELOCITY (FROM RAINFALL ONLY) %s',tcs,sWarn);
            end
        case 'L2'
            if ~TR
                emailText = sprintf(...
                    'Time %s - PRE-ALERT, TRANSITION LOW/MEDIUM VELOCITY (FROM RAINFALL ONLY)',tcs);
            else
                emailText = sprintf(...
                    'Time %s - WARNING - PRE-ALERT (FROM RAINFALL ONLY) %s',tcs,sWarn);
            end
        case 'L3'
            if ~TR
                emailText = sprintf(...
                    'Time %s - ALWAYS PRE-ALERT, MEDIUM VELOCITY (FROM RAINFALL ONLY)',tcs);
            else
                emailText = sprintf(...
                    'Time %s - WARNING - ALWAYS PRE-ALERT (FROM RAINFALL ONLY) %s',tcs,sWarn);
            end
        case 'L4'
            emailText = sprintf(...
                'Time %s - ALARM, TRANSITION TO HIGH VELOCITY (FROM RAINFALL ONLY)',tcs);
        case 'L5'
            emailText = sprintf(...
                'Time %s - ALWAYS ALARM, HIGH VELOCITY (FROM RAINFALL ONLY)',tcs);
        case 'L6'
            emailText = sprintf(...
                'Time %s - TOWARDS ALARM RETURN, TRANSTION FROM HIGH TO MEDIUM VELOCITY (FROM RAINFALL ONLY)',tcs);
        case 'L7'
            emailText = sprintf(...
                'Time %s - TOWARDS PRE-ALERT RETURN, TRANSTION FROM MEDIUM TO LOW VELOCITY (FROM RAINFALL ONLY)',tcs);
    end
else        % no forecast
    emailText = sprintf(...
        'Time %s - THE CNN-BASED SYSTEM IS UNABLE TO PROVIDE FORECASTS',tcs);
end

sendmail(emailReceivers,emailSubject,emailText);

disp('... done');

% exit          % please uncomment to have exit as PluVelOpera runs 